package com.xinz.server.socket;

import java.util.ArrayList;
import java.util.List;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelLocal;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xinz.Constants;
import com.xinz.protocal.Buffer;
import com.xinz.protocal.Log;
import com.xinz.protocal.NativeInterfaceProvider;
import com.xinz.protocal.Session;
import com.xinz.protocal.SrmiDefine;
import com.xinz.protocal.client.RemoteInvoker;
import com.xinz.protocal.config.ConfigFactory;
import com.xinz.protocal.server.NativeInvoker;
import com.xinz.server.SessionListener;
import com.xinz.shared.player.PlayerInterface;

public class SpotNettySocketHandler extends SimpleChannelHandler{

	private static final Logger log = LoggerFactory.getLogger(SpotNettySocketHandler.class);
	
	private static final Logger logFlow = LoggerFactory.getLogger("FLOW");
	
	static final String SRMI_SESSION = "srmi_session";
	
	static final String NETTY_CHANNEL = "netty_channel";
	
	NativeInvoker invoker;
	
	NativeInterfaceProvider interfaceProvider;
	
	ConfigFactory factory;
	
	List<SessionListener> listeners = new ArrayList<SessionListener>();
	
	ChannelLocal<Session> channelSession = new ChannelLocal<Session>(true);
	
	public SpotNettySocketHandler(ConfigFactory factory) {
		Log.warning("new init ...");
		this.invoker = new NativeInvoker(factory);
		this.factory = factory;
		this.interfaceProvider = new NativeInterfaceProvider();
	
	}
	
	public void addSessionListener(SessionListener listener) {
		listeners.add(listener);
	}
	
	@Override
	public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{
		Log.warning("open ...");
		log.info("session creat:" + ctx.getChannel());
		super.channelOpen(ctx, e);
		Session spotSession = new Session(interfaceProvider);
		RemoteInvoker invoker = new RemoteInvoker(factory, new SocketChannelInvokeConnector(spotSession, e.getChannel()));
		spotSession.initInvoker(invoker);
		spotSession.setTag(NETTY_CHANNEL, e.getChannel());
		channelSession.set(e.getChannel(), spotSession);
		for(SessionListener listener : listeners) {
			listener.onSessionCreate(spotSession);
		}
	}
	
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
		Session session = null;
		String uid = "";
		try {
			Buffer buffer = (Buffer) e.getMessage();
			session = channelSession.get(e.getChannel());
			
			Buffer result = invoker.invoke(session, buffer);
			uid = (String) session.getTag(Constants.SESSION_ID);
			if(buffer.type == SrmiDefine.TYPE_REQUEST) {
				result.type = SrmiDefine.TYPE_RETURN;
				e.getChannel().write(result);
			}
		}
		catch(Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		finally {
			//Session session = Session.getCurrent();
			//String uid = (String)session.getTag(Constants.SESSION_UID);
			
			// FLOW日志
		}
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception{
		super.exceptionCaught(ctx, e);
		System.out.println(ctx.getChannel());
		log.error("异常" + e.getCause(), e);
	}
	
	@Override
	public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{
		log.info("session close:" + ctx.getChannel());
		super.channelClosed(ctx, e);
		for(SessionListener listener : listeners) {
			listener.onSessionClose(channelSession.get(e.getChannel()));
		}
	}
}
